package com.xingzhe.content.service.jobhandler;

import com.xingzhe.base.exception.XingZhePlusException;
import com.xingzhe.content.feignclient.CourseIndex;
import com.xingzhe.content.feignclient.SearchServiceClient;
import com.xingzhe.content.mapper.CoursePublishMapper;
import com.xingzhe.content.model.po.CoursePublish;
import com.xingzhe.content.service.CoursePublishService;
import com.xingzhe.messagesdk.model.po.MqMessage;
import com.xingzhe.messagesdk.service.MessageProcessAbstract;
import com.xingzhe.messagesdk.service.MqMessageService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class CoursePublishTask extends MessageProcessAbstract {

    @Autowired
    CoursePublishService coursePublishService;

    @Resource
    CoursePublishMapper coursePublishMapper;

    @Resource
    SearchServiceClient searchServiceClient;

    @Resource
    RedisTemplate redisTemplate;

    //任务调度入口
    @XxlJob("CoursePublishJobHandler")
    public void coursePublishJobHandler() throws Exception {

        //分片任务的参数
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号
        int shardTotal = XxlJobHelper.getShardTotal();//执行器的数量
        process(shardIndex,shardTotal,"course_publish",30,60);
    }




    //课程发布任务处理
    @Override
    public boolean execute(MqMessage mqMessage) {
        //拿到courseId
        long courseId = Long.parseLong(mqMessage.getBusinessKey1());
        //课程静态化并上传到minio
        generateCourseHtml(mqMessage,courseId);
        //向elastic search写索引数据
        saveCourseIndex(mqMessage,courseId);
        //向redis写入缓存
        saveCache(mqMessage,courseId);
        //返回true代表任务成功
        return true;
    }

    //生成课程静态化页面并上传至文件系统  第一阶段
    public void generateCourseHtml(MqMessage mqMessage,long courseId){
        log.debug("开始进行课程静态化,课程id:{}",courseId);
        //做任务的幂等性处理
        //查询数据库取出现阶段的执行状态
        //消息任务id
        Long taskId = mqMessage.getId();
        //消息处理的service
        MqMessageService mqMessageService = this.getMqMessageService();
        //消息幂等性处理
        int stageOne = mqMessageService.getStageOne(taskId);
        if(stageOne >0){
            log.debug("课程静态化已处理直接返回，课程id:{}",courseId);
            return;
        }
        //开始进行课程静态化 生成HTML页面
        File file = coursePublishService.generateCourseHtml(courseId);
        if (file==null){
            XingZhePlusException.cast("生成的静态页面为空");
        }
        //将HTML上传到minio
        coursePublishService.uploadCourseHtml(courseId,file);
        //保存第一阶段状态
        mqMessageService.completedStageOne(taskId);

    }

    //保存课程索引信息   第二阶段
    private void saveCourseIndex(MqMessage mqMessage,long courseId){
        //消息任务id
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        //取出第二个阶段的状态
        int stageTwo = mqMessageService.getStageTwo(taskId);
        //任务幂等性的处理
        if (stageTwo>0){
            log.debug("课程索引信息以写入，无需执行。。。");
            return;
        }
        //查询课程信息，调用搜索服务添加索引
        CoursePublish coursePublish = coursePublishMapper.selectById(courseId);
        CourseIndex courseIndex = new CourseIndex();
        BeanUtils.copyProperties(coursePublish,courseIndex);
        //远程调用搜索服务
        Boolean add = searchServiceClient.add(courseIndex);
        if (!add){
            XingZhePlusException.cast("远程调用搜索服务的添加课程索引api失败.....");
        }
        //完成第二阶段任务
        mqMessageService.completedStageTwo(taskId);
    }

    private void saveCache(MqMessage mqMessage,long courseId){
        //消息任务id
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        int stageThree = mqMessageService.getStageThree(taskId);
        //任务幂等性的处理
        if (stageThree>0){
            log.debug("课程缓存信息以写入，无需执行。");
            return;
        }

        //查询课程信息
        CoursePublish coursePublish = coursePublishMapper.selectById(courseId);
        //将课程信息缓存到redis
        redisTemplate.opsForValue().set(courseId,coursePublish,7,TimeUnit.DAYS);
        //保存第三阶段任务状态
        mqMessageService.completedStageThree(taskId);
    }


}
